#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<immintrin.h>
#include<time.h>
long img[1920][1080];
long img_orig[1920][1080];

void read_img() {
	FILE* f = NULL;
	f = fopen("img.txt", "r");
	int a = 0;
	for (int i = 0; i < 1920; i++) {
		for (int j = 0; j < 1080; j++) {
			fscanf(f, "%d", &a);
			img_orig[i][j] = a;
		}
	}
	fclose(f);
	memcpy(img, img_orig, 1920 * 1080 * 4);
}
void write_img() {
	FILE* f = NULL;
	f = fopen("img_dest.txt", "w");
	int a = 0;
	fprintf(f, "[");
	for (int i = 0; i < 1919; i++) {
		fprintf(f, "[");
		for (int j = 0; j < 1079; j++) {
			a = img[i][j];
			fprintf(f, "%d,", a);
		}
		a = img[i][1079];
		fprintf(f, "%d],\n", a);
	}
	fprintf(f, "[");
	for (int j = 0; j < 1079; j++) {
		a = img[1919][j];
		fprintf(f, "%d,", a);
	}
	a = img[1919][1079];
	fprintf(f, "%d]]\n", a);
	fclose(f);
}

void img_smooth() {
	memcpy(img, img_orig, 1920 * 1080 * 4);
	for (int i = 1; i < 1919; i++) {
		for (int j = 1; j < 1079; j++) {
			img[i][j] = (img_orig[i - 1][j] +
				img_orig[i + 1][j] +
				img_orig[i][j + 1] +
				img_orig[i][j - 1]) /4;
		}
	}
}

void img_smooth1() {
	long img_tmp[1080];
	long last_pixel = 0;
	long temp_pixel = 0;
	memcpy(img_tmp + 1, img_orig[0] + 1, 1078 * 4);
	for (int i = 1; i < 1919; i++) {
		last_pixel = img[i][0];
		for (int j = 1; j < 1079; j++) {
			temp_pixel = img[i][j];
			img[i][j] = (img_tmp[j] +
				img[i + 1][j] +
				img[i][j + 1] +
				last_pixel) >> 2;
			last_pixel = temp_pixel;
			img_tmp[j] = temp_pixel;
		}
	}
}

void img_smooth_avx() {
	__m256i v0;
	__m256i v1;
	__m256i v2;
	__m256i v3;
	int i;
	int j;
	for (i = 1; i < 1919; i++) {
		for (j = 1; j < 1079 - 8; j += 8) {
			v0 = _mm256_loadu_si256(img_orig[i - 1] + j);
			v1 = _mm256_loadu_si256(img_orig[i + 1] + j);
			v1 = _mm256_add_epi32(v0, v1);
			v2 = _mm256_loadu_si256(img_orig[i] + j - 1);
			v2 = _mm256_add_epi32(v1, v2);
			v3 = _mm256_loadu_si256(img_orig[i] + j + 1);
			v3 = _mm256_add_epi32(v2, v3);
			v3 = _mm256_srli_epi32(v3, 2);
			_mm256_storeu_si256(img[i] + j, v3);
		}
		v0 = _mm256_loadu_si256(img_orig[i - 1] + 1071);
		v1 = _mm256_loadu_si256(img_orig[i + 1] + 1071);
		v1 = _mm256_add_epi32(v0, v1);
		v2 = _mm256_loadu_si256(img_orig[i] + 1070);
		v2 = _mm256_add_epi32(v1, v2);
		v3 = _mm256_loadu_si256(img_orig[i] + 1072);
		v3 = _mm256_add_epi32(v2, v3);
		v3 = _mm256_srli_epi32(v3, 2);
		_mm256_storeu_si256(img[i] + 1071, v3);
	}
}

int main() {
	read_img();
	clock_t end;
	clock_t start = clock();
	for (int i = 0; i < 1000; i++) {
		img_smooth();
	}
	end = clock();
	printf("img_smooth\ttime:%dms\n", end - start);
	start = clock();
	for (int i = 0; i < 1000; i++) {
		img_smooth1();
	}
	end = clock();
	printf("img_smooth1\ttime:%dms\n", end - start);
	start = clock();
	for (int i = 0; i < 1000; i++) {
		img_smooth_avx();
	}
	end = clock();
	printf("img_smooth_avx\ttime:%dms\n", end - start);
	write_img();
	return 0;
}